<!--
  * @Author: 郝奔 1425466221@qq.com
  * @Date: 2024-07-09 09:51:05
 * @LastEditors: 郝奔 1425466221@qq.com
 * @LastEditTime: 2024-12-18 11:57:34
  * @FilePath: \weshyper_dev_vue2\src\framework\unified-navigation\views\components\menu-search\views\content-dialog.vue
  * @Description: 
  * Copyright (c) 2024-present HBIS Digital Technology Co.,Ltd. All rights reserved. 
-->
<template>
  <div class="search-mask" @click="emit('close')">
    <div class="search-contentDialog" style="overflow-y: hidden;"
      :style="{ 'height': options.length === 0 ? '222px' : '410px' }" @click.stop="">
      <div class="searchResult">
        <el-input ref="input" v-model.trim="search" :prefix-icon="Search" placeholder="请输入关键字进行搜索" />
        <div v-if="options.length === 0" class="noResult">
          <span>没有搜索结果</span>
        </div>

        <div v-else class="haveResult">
          <span class="result-explain">
            菜单及应用
          </span>

          <ul>
            <li v-for="(option, index) in options" :key="index" role="option" :class="{ isSelectMenu: num == index }">
              <!-- {{ option.item }} -->
              <div class="li-content" :class="{ active: num == index || mouseNum == index }"
                @mouseenter="hoverFunc(index)" @click="change(option)">
                <!-- 应用 -->
                <template v-if="option.type == 0">
                  <DtSvgIcon v-if="num == index || mouseNum == index" style="margin-right: 6px;"
                    icon-class="app-icon-blue" />

                  <DtSvgIcon v-else style="margin-right: 6px;" icon-class="app-icon" />
                </template>

                <!-- 菜单 -->
                <template v-else-if="option.type == 1">
                  <!-- 应用与菜单同时有关键字的展示层级关系图标 -->
                  <template v-if="option.isSecond">
                    <DtSvgIcon v-if="num == index || mouseNum == index" style="margin-right: 6px;"
                      icon-class="second-menu-blue" />

                    <DtSvgIcon v-else style="margin-right: 6px;" icon-class="second-menu" />
                  </template>

                  <DtSvgIcon v-if="num == index || mouseNum == index" style="margin-right: 6px;"
                    icon-class="search-menu-blue" />

                  <DtSvgIcon v-else style="margin-right: 6px;" icon-class="search-menu" />
                </template>


                <span :class="{ active: num == index || mouseNum == index }"
                  v-dompurify-html="highlightText(option.title, search)" />

                <DtSvgIcon v-if="num == index" style="float: right;margin-top: 5px;" icon-class="search-enter-sure" />
              </div>
            </li>
          </ul>
        </div>
      </div>

      <!-- <dt-HeaderSearch id="header-search" class="right-menu-item" /> -->

      <div class="searchFooter">
        <DtSvgIcon size="2em" icon-class="search-enter" />

        <span>搜索</span>

        <DtSvgIcon size="2em" icon-class="search-down" />

        <DtSvgIcon size="2em" icon-class="search-up" />

        <span>切换</span>

        <DtSvgIcon size="2em" icon-class="search-esc" />

        <span>关闭</span>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { searchByAppOrMenuName } from '../../api/index'
// import { getToken } from '@/framework/utils/auth'
import { debounce } from 'throttle-debounce'
import { icons } from '@hbisdt-design/icons-vue'
import { openOrPushUrl } from '../../../../../utils/index'
const {Search} = icons

const state = reactive({
  search: '',
  num: 0,
  mouseNum: 0
})
const { search, num, mouseNum } = toRefs(state)
const emit = defineEmits(['close'])
interface optionsType {
  isSecond?: boolean,
  type: number,
  title: string,
  path: string
}
const options = ref<optionsType[]>([])
const input = ref()
const querySearchDebounce = debounce(340, (val: string) => {
  querySearch(val)
})
watch(search, (newVal) => {
  querySearchDebounce(newVal)
})
const querySearch = (query: string): void => {
  if (query !== '') {
    searchByAppOrMenuName({ name: query }).then(res => {
      const list: optionsType[] = []
      res.data.forEach(v => {
        list.push({
          ...v,
          type: 0,
          title: v.appName,
          path: v.appAddress + (v.defaultMenuPath || '')
          // path: v.appAddress + (specialData.includes(v.appCode) ? '' : (v.defaultMenuPath || ''))
        })
        v.menuList.forEach(k => {
          list.push({
            ...k,
            isSecond: true,
            type: 1,
            title: k.menuName,
            path: v.appAddress + k.menuPath
          })
        })
      })
      options.value = list
    })
  } else {
    options.value = []
  }
}
/**
 * 按键事件
 */
const handleKey = (e: KeyboardEvent): void => {
  // Up Arrow
  if (e.key === 'ArrowUp') {
    if (num.value > 0) {
      num.value--
    } else {
      num.value = options.value.length - 1
    }
    domSmmoth()
  }
  // Dw Arrow
  if (e.key === 'ArrowDown') {
    if (num.value < options.value.length - 1) {
      num.value++
    } else {
      num.value = 0
    }
    domSmmoth()
  }
  // Enter
  if (e.key === 'Enter') {
    change(options.value[num.value])
  }

  // esc
  if (e.key == 'Escape') {
    emit('close')
  }
}
const domSmmoth = (): void => {
  nextTick().then(() => {
    const selectedElement = document.querySelector('.search-mask .isSelectMenu')
    if (selectedElement) {
      selectedElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
  })
}
onMounted(() => {
  // 监听键盘事件
  document.addEventListener('keydown', handleKey)
  nextTick(() => {
    input.value.focus()
  })
})
const hoverFunc = (val: number): void => {
  mouseNum.value = val
}

const change = (item: optionsType): void => {
  openOrPushUrl(item, item.path)
  emit('close')
  // item && item.path && window.open(`${item.path}?token=${getToken()}`)
}
/**
 * @description: 高亮显示关键字
 * @return {*}
 */
const highlightText = (text: string, query: string): string => {
  if (!query) {
    return text
  }
  const queryRegex = new RegExp(`(${query.replace(/[-/\\$*+?.()|[\]{}]/g, '\\$&')})`, 'gi')
  return text.replace(queryRegex, '<span class="highlight" style="color: #004fff;">$1</span>')
}
onUnmounted(() => {
  document.removeEventListener('keydown', handleKey)
})
</script>

<style lang="scss" scoped>
.search-mask {
  position: fixed;
  overflow: hidden;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 2000;
  background-color: rgba($color: #fff, $alpha: 0.8);
  display: flex;
  align-items: center;
  justify-content: center;

  .search-contentDialog {
    position: relative;
    width: 560px;
    z-index: 2001;
    margin: 0 auto;
    text-align: center;
    background: #fafafa;
    border: 1px solid #fafafa;
    /* 边框 */
    border-bottom-left-radius: 10px;
    border-bottom-right-radius: 10px;
    //   box-shadow: 0 4px 8px rgb(0 0 0 / 70%); /* 阴影 */
    box-shadow: 0 2px 4px -2px rgb(0 0 0 / 12%), 0 4px 8px 0 rgb(0 0 0 / 8%), 0 4px 16px 4px rgb(0 0 0 / 4%);

    .searchResult {
      height: 100%;
      padding: 12px;

      .haveResult {
        height: 310px;
        overflow: scroll;

        .result-explain {
          display: block;
          margin: 12px 0 6px;
          color: #004fff;
          font-size: 14px;
          text-align: left;
        }

        ul {
          margin-top: 0 !important;
          padding: 0;
          overflow: scroll;
          list-style: none;

          .li-content {
            padding: 12px;
            text-align: left;
          }

          .active {
            color: #004fff;
            background: #e8f3ff;
          }

          // li:hover,
          // li:focus {
          //   background: #e8f3ff;
          // }
        }
      }
    }

    .searchFooter {
      position: absolute;
      bottom: 0;
      display: flex;
      align-items: center;
      width: 100%;
      height: 50px;
      padding: 12px;
      box-shadow: 0 -1px 0 0 #e0e3e8, 0 -3px 6px 0 rgb(69 98 155 / 12%);

      .svg-icon {
        width: 2em;
        height: 2em;
      }

      span {
        margin-right: 12px;
        color: #606266;
        font-size: 12px;
      }
    }

    :deep(.el-input__prefix) {
      color: #004fff;
    }

    .noResult {
      margin-top: 52px;

      span {
        color: #c0c4cc;
        font-weight: 400;
        font-size: 12px;
      }
    }
  }
}
</style>